package it.polimi.digitalstate.persist;

import it.polimi.digitalstate.dto.CitizenDTO;
import it.polimi.digitalstate.dto.UserDTO;
import it.polimi.digitalstate.entities.*;
import it.polimi.digitalstate.manager.DTOEntityTransformer;

import javax.persistence.EntityManager;
import javax.persistence.Query;

/**
 * SuperEntityManager, make an entity persistent in the database just like EntityManager but have more features:
 * Check the data consistency before (but this is done also by the JPA Annotation)
 * Arise the right exception in such a way that the web tier is able to understand what constraint has to be fixed
 */
public class SuperEntityManager {

	/**
	 * Make the party created persistent in the database
	 * @param em Entity Manager used
	 * @param entity The given party
	 * @throws SuperEntityManagerException (UniquePartyNameException if the name is already found in the database, UniquePartySymbolException for the same issue on the Symbol)
	 */
	public void persist(EntityManager em, Party entity) throws SuperEntityManagerException{
		if(entity instanceof Party ){
			Query q = em.createNamedQuery("party_getByName");
			q.setParameter("name", ((Party) entity).getName());
			if(q.getResultList().toArray().length >= 1){
				throw new UniquePartyNameException();
			}
			q = em.createNamedQuery("party_getBySymbol");
			q.setParameter("symbol", ((Party) entity).getSymbol());
			if(q.getResultList().toArray().length >= 1){
				throw new UniquePartySymbolException();
			}
			em.persist(entity);
		}
	}

	/**
	 * Make the user persistent in the database
	 * This is almost the feature of "registration"
	 * @param em Entity Manager used
	 * @param user
	 * @param citizen
	 * @throws SuperEntityManagerException (UniquePartyNameException if the name is already found in the database, UniquePartySymbolException for the same issue on the Symbol)
	 */
	public void persist(EntityManager em, UserDTO user, CitizenDTO citizen) throws SuperEntityManagerException{
		
			/*unique username check*/
			Query q = em.createNamedQuery("user_getByUsername");
			q.setParameter("username", user.getUsername());
			if(q.getResultList().toArray().length >= 1){
				throw new UniqueUserUsernameException();
			}
			
			/*unique email check*/
			q = em.createNamedQuery("user_getByEmail");
			q.setParameter("email", user.getEmail());
			if(q.getResultList().toArray().length >= 1){
				throw new UniqueUserEmailException();
			}
			
			/*existing ecode check*/
			q = em.createNamedQuery("citizen_getByEcode");
			q.setParameter("ecode", citizen.getEcode());
			if(q.getResultList().toArray().length < 1){
				throw new InvalidCitizenEcode();
			}
			Citizen c = (Citizen)q.getResultList().toArray()[0];
			
			/*correct couple ecode->citizen*/
			if(!(citizen.getName().equalsIgnoreCase(c.getName())
					&& citizen.getSurname().equalsIgnoreCase(c.getSurname()) 
					&& citizen.getDob().equals(c.getDob()))){
				throw new UncorrectCitizenEcodeMatch();
			}
			
			/*check if the given citizen is alredy registered with some account*/
			q = em.createNamedQuery("user_getByCitizen");
			q.setParameter("citizen", c);
			if(q.getResultList().toArray().length >0){
				throw new AccountAlreadyExistingException();
			}
			
			/*persist*/
			User new_user= new User(user,c);
			em.persist(new_user);
	}
}
